#COMBAT TESTS
import unittest

import game.combat.models as c
import game.damage.models as d
import game.actions.models as a
import game.monster.models as m
from game.monster.tests import baseGroupTest, basicTest
from game.combat.combatActionRequest import combatActionRequest

class damageModifierCollectionTest(unittest.TestCase):
	
	def setUp(self):
		self.dmc = d.damageModifierCollection.objects.create(
		basePhysicalDefence=1, baseMagicalDefence = 2)
		self.dtp= d.damageType.objects.create(name='PhysicalDamage',
					physical=1)
		self.dtm= d.damageType.objects.create(name='MagicalDamage',
					physical=0)
		self.dtx= d.damageType.objects.create(name='TestDamage',
					physical=1)
		self.dm1= d.damageModifier.objects.create(damageType = self.dtp,
					power=3, damageModifierCollection = self.dmc)
		self.dm2= d.damageModifier.objects.create(damageType = self.dtm,
					power=4, damageModifierCollection= self.dmc)
					
	def tearDown(self):
		d.damageType.delete(self.dtp)
		d.damageType.delete(self.dtm)
		d.damageType.delete(self.dtx)
		d.damageModifier.delete(self.dm1)
		d.damageModifier.delete(self.dm2)
		d.damageModifierCollection.delete(self.dmc)
					
	def testRelationCount(self):
		""" Test Collection has the proper damage modifiers """
		self.assertEquals(self.dmc.damagemodifier_set.values().count(), 2)
	
	def testResistance(self):
		""" tests the proper value is returned for each damageType"""
		self.assertEquals(self.dmc.getDefence(self.dtp), 3)
		self.assertEquals(self.dmc.getDefence(self.dtm), 4)
		self.assertEquals(self.dmc.getDefence(self.dtx), 1)

class attackTest(unittest.TestCase):
	
	def setUp(self):
		self.dt = d.damageType.objects.create(name='Test', physical = 1)
		self.attack = a.attack.objects.create(name='Test Attack',
					damageType = self.dt,diceSize=10, diceNum=1, 
					power=1,attemptMessage = "Trying to attack", successMessage = "Hit",failureMessage = "Missed",
					getSuccessMethod ="alwaysHit", successMethod = "alwaysHit", failureMethod ="alwaysHit" )
					
	def tearDown(self):
		a.attack.delete(self.attack)
		d.damageType.delete(self.dt)
		
	def testAttack(self):
		"""Generate a proper damage"""
		self.dam=self.attack.damage
		self.assertEquals(self.dam.damageType, self.dt)
		self.assert_(self.dam.amount in range(1,11),"Damage outside of valid range")
	
	def testAddDamage(self):
		self.dam = self.attack.damage
		self.initialDam=self.dam.amount
		self.dam.addDamage(5)
		self.assertEquals(self.dam.amount,self.initialDam+5)
		self.dam.addDamage('Bogus')
		self.assertEquals(self.dam.amount,self.initialDam+5)

class groupCombatTest(baseGroupTest, attackTest):
	
	def setUp(self):
		baseGroupTest.setUp(self)
		attackTest.setUp(self)
		self.species.actions.add(self.attack)
		self.combat = c.combat.objects.create(sideA=self.group, sideB=self.group2)
		self.combatant1 = self.combat.addIndividualToCombat(self.individual1, control=1)
		self.combatant2 = self.combat.addIndividualToCombat(self.individual2, control=1)
		self.combatant3 = self.combat.addIndividualToCombat(self.individual3, control=1)
		self.combatant4 = self.combat.addIndividualToCombat(self.individual4, control=1)
		
	def tearDown(self):
		baseGroupTest.tearDown(self)
		attackTest.tearDown(self)	
		c.combat.delete(self.combat)
		
	def testCombatGroup(self):
		""" test combat functions that call group """
		self.assertEquals(len(self.combat.allCombatants()), 4)
	
	def testNextMonster(self):
		"""tests getNextCombatant iterates properly"""
		monsters=self.combat.allCombatants()
		self.combat.currentCombatant=monsters[0]
		self.combat.getNextCombatant()
		self.assertEquals(self.combat.currentCombatant, monsters[1])
		
	def testGetAllies(self):
		"""test that getAllies works"""
		combatant = c.combatant.objects.get(individual = self.individual1)
		allies = combatant.getAllies()
		self.assert_(self.combatant1 in allies)
		self.assert_(self.combatant2 in allies)
		self.assert_(self.combatant3 in allies)
		self.assert_(self.combatant4 not in allies)
		
	def testGetEnemies(self):
		"""tests that getEnemies works"""
		combatant = c.combatant.objects.get(individual = self.individual1)
		enemies = combatant.getEnemies()
		self.assert_(self.combatant1 not in enemies)
		self.assert_(self.combatant2 not in enemies)
		self.assert_(self.combatant3 not in enemies)
		self.assert_(self.combatant4 in enemies)
		
#	def testNextMonster2(self):
#		"""Tests that getNextCombatant loops back to the start properly"""
#		monsters = self.combat.allCombatants()
#		self.combat.currentCombatant=monsters[3]
#		self.combat.save()
#		self.assertEquals(self.combat.currentCombatant.id, monsters[0].id)
class combatActionRequestTest(groupCombatTest):
	
	def setUp(self):
		groupCombatTest.setUp(self)
		self.car = combatActionRequest(self.attack, self.combatant1, self.combatant4, self.combat)
		
	def tearDown(self):
		groupCombatTest.tearDown(self)

	def testCombatActionRequest(self):
		#print self.attack.successMethod
		print "Processing"
		self.combat.processRequest(self.car)
		print self.combat.getMessages()
		print self.combat.id
		print c.combatMessage.objects.all()
		
		
class damageIndividualTest(attackTest, basicTest):
	
	def setUp(self):
		attackTest.setUp(self)
		basicTest.setUp(self)
		self.individual = m.individual.objects.create(species = self.species,
			firstName = 'test1', lastName='test1')
		self.individual.totalHP = 20
		self.individual.save()
		
	def tearDown(self):
		attackTest.tearDown(self)
		basicTest.tearDown(self)
		m.individual.delete(self.individual)
		
	def testApplyDamage(self):
		damage = self.attack.damage.applyDamage(self.individual)
		self.assertEquals(self.individual.hpLeft,
			(self.individual.totalHP - damage))
			
	def testDamageDoesntExceedHP(self):
		#generates more damage than an individual has
		#ensures that individual damage greater than its HP
		self.attack.diceNum = 2
		self.attack.save()
		self.attack.damage.amount = 10
		self.individual.totalHP = 1
		damage = self.attack.damage.applyDamage(self.individual)
		self.assert_(self.individual.damage <= self.individual.totalHP)
